/*******************************************************************************
 * 版权：北京润尼尔网络科技有限公司，保留所有版权<br>
 * 版本：v1.0.0<br>
 * 文件：Draw2dGraphicalEditor.js<br>
 * 日期：2016年10月11日<br>
 * 作者: 王志远<br>
 * 功能：2d图形编辑器<br>
 *
 * 修改记录：<br>
 * 日期 描述 更新功能<br>
 ******************************************************************************/

window.makeNamespace(window, "Rainier.UI.V2");

/**
 * 类型名称：Rainier.UI.V2.Draw2dGraphicalEditor<br>
 * 类型功能：编辑器基类<br>
 */
Rainier.UI.V2.Draw2dGraphicalEditor = Rainier.UI.V2.GraphicalEditor.extend({
  NAME: "Rainier.UI.V2.Draw2dGraphicalEditor",

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.init<br>
   * 函数功能：构造函数<br>
   * 参数输入：objPro:ViewProperty
   * 异常信息：无<br>
   */
  init: function (objPro) {
    this._super(objPro);
    this.rootEditPart = new Rainier.UI.V2.RootEditPart();
    this.rootModel = new Rainier.UI.V2.RootModel();
    this.context = new Rainier.UI.V2.Draw2dContext();
    this.runStatus = false; //判断当前实验是否处于解算状态
    this.storageExper = null;

    this.virtualModelList = {}; //存储虚拟仪器列表，方便动态调用
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.storeExper<br>
   * 函数功能：存储默认实验(主针对集成环境)<br>
   * 参数输入：exper ： Object<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  storeExper: function (exper) {
    this.storageExper = exper;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.onPropertyChange<br>
   * 函数功能：侦听模型事件信息<br>
   * 参数输入：evt:PropertyChangeEvent<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  onPropertyChange: function (evt) {
    var eventName = evt.getEventName();
    var oldValue = evt.getOldValue();
    var newValue = evt.getNewValue();
    this.editorObjectEventSupport.firePropertyChangeEvent(eventName, oldValue, newValue);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.createComposite<br>
   * 函数功能：创建组件<br>
   * 参数输入：parent:父组件<br>
   * 参数输入：uiProperty界面属性<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  createComposite: function (parent, uiProperty, size) {
    var _this = this;
    var canvasComposite = new Rainier.UI.V2.UICompositeDraw2dCanvas(parent, { width: 5000, height: 5000 });

    //变量初始化
    var canvas = canvasComposite.canvas; //绘图帆布
    var rootEditPart = this.rootEditPart; //根编辑器
    var rootModel = this.rootModel; //根模型
    var context = this.context; //编辑器上下文环境
    // if (size) {
    //   canvas.setZoom(canvas.getZoom() * 1.4, true);
    // } else {
    //   canvas.setZoom(canvas.getZoom() * 1.2, true);
    // }

    // canvas.enableWheel();

    //设置图元EditPolicy
    this.rootEditPart.setFigure(canvas);
    this.rootEditPart.setModel(rootModel);

    //初始化上下文环境
    this.context.setRootEditPart(rootEditPart);
    this.context.setRootModel(rootModel);
    this.context.setRootFigure(canvas);
    this.context.setCircuitParser();

    //初始化命令堆栈
    this.commandStack = canvas.getCommandStack();

    //侦听模型事件
    this.rootEditPart.addModelEventListener("modelEventListener", this);
    this.rootEditPart.addModelEventListener("modelEventListenerForContext", this.context);

    //初始化组件（组件赋值）
    this.composite = canvasComposite;

    // var Listener = Rainier.UI.V2.UIEventListener.extend({

    // 	NAME : 'listener',

    // 	init : function(){
    // 		this._super();
    // 	},

    // 	onEvent : function(sEvent,eventSource,args){
    // 		var width  = args[0];
    // 		var height = args[1];
    // 		var zoom = canvas.getZoom();
    // 		if(width < _this.initWidth){
    // 			canvas.setZoom(zoom + 0.3,true);
    // 			_this.initWidth = width;
    // 		}else if(width > _this.initWidth){
    // 			canvas.setZoom(zoom - 0.3,true);
    // 			_this.initWidth = width;
    // 		}
    // 	},
    // });

    // parent.registerEventListener("onResize",new Listener());

    if (this.storageExper) {
      this.doRestore(this.storageExper);
    }
    canvas.setZoom(canvas.getZoom() - 0.5, true);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.installEditPartFactory<br>
   * 函数功能：安装元件创建工厂<br>
   * 参数输入：factory:Rainier.UI.V2.EditPartFactory<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  installEditPartFactory: function (factory) {
    this.rootEditPart.installEditPartFactory(factory);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.enterCreateState<br>
   * 函数功能：进入器件创建状态<br>
   * 参数输入：sModelClassName:String<br>
   * 参数输出：modelProperty:{
   * 		uiProperty:{
   * 		},
   * 		modelProperty:{
   * 		}
   * }<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  enterCreateState: function (sModelClassName, modelProperty, sJson) {
    this.rootEditPart.enterCreateState(sModelClassName, modelProperty, sJson);
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.enterRunStatus<br>
   * 函数功能：进入解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  enterRunStatus: function () {
    this.getVirtualModel();
    var dsvList = this.getDSVirtualModel();
    $.each(dsvList, function (index, dsv) {
      dsv.startCvi(true);
    });
    $.each(this.virtualModelList, function (i, model) {
      model.sendStartToCvi("restart");
    });
    this.runStatus = true;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.leaveRunStatus<br>
   * 函数功能：退出解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  leaveRunStatus: function () {
    var dsvList = this.getDSVirtualModel();
    $.each(dsvList, function (index, dsv) {
      dsv.closeCvi();
    });
    $.each(this.virtualModelList, function (i, model) {
      model.sendStartToCvi("stop");
    });
    this.runStatus = false;
    this.virtualModelList = {};
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getRunStatus<br>
   * 函数功能：获取解算状态<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getRunStatus: function () {
    return this.runStatus;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.getRootModel<br>
   * 函数功能：获取rootModel<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getRootModel: function () {
    return this.rootModel;
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getDSVirtualModel<br>
   * 函数功能：获取所有启动虚拟仪器<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getVirtualModel: function () {
    var _this = this;
    var children = this.rootModel.getChildren();
    this.virtualModelList = {};
    $.each(children, function (index, child) {
      if (child instanceof Rainier.UI.V2.VirtualModel) {
        var label = child.getProperty().modelProperty.label;
        if (label) {
          _this.virtualModelList[label.toLowerCase()] = child;
        }
      }
    });
  },

  /**
   * 函数名称：Rainier.UI.V2.Draw2dGraphicalEditor.getDSVirtualModel<br>
   * 函数功能：获取默认启动虚拟仪器<br>
   * 参数输入：无<br>
   * 参数输出：无<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  getDSVirtualModel: function () {
    var _this = this;
    var unitList = [];
    var children = this.rootModel.getChildren();
    $.each(children, function (index, child) {
      if (child instanceof Rainier.UI.V2.DSVirtualModel) {
        unitList.push(child);
      }
    });
    return unitList;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doSave<br>
   * 函数功能：执行保持<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doSave: function (expName) {
    var json = {};

    var description = {};
    var version = null;
    var modelJson = null;
    var user = null;

    if (this.rootModel) {
      modelJson = this.rootModel.serializeToJson();
    }

    //填充基本信息
    json.experimentInfo = {};
    json.experimentInfo.experimentName = expName;
    json.experimentInfo.configuretion = this.context.experimentCfg || "";
    json.experimentInfo.zoom = this.context.getRootFigure().getZoom();

    //填充实验脚本
    json.experimentScene = modelJson;

    //填充实验步骤信息
    json.stepByStep = [];

    return json;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doSaveAs<br>
   * 函数功能：执行另存为<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doSaveAs: function (expName) {
    var json = this.doSave(expName);
    return json;
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.doRestore<br>
   * 函数功能：执行恢复过程<br>
   * 参数输入：objJson Json格式对象输入<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  doRestore: function (objJson) {
    this.clearEditor();
    var _this = this;
    var components = null;
    var connections = null;

    if (objJson.experimentInfo.configuretion) {
      _this.context.experimentCfg = objJson.experimentInfo.configuretion;
    }
    if (objJson.experimentInfo.zoom) {
      _this.context.getRootFigure().setZoom(objJson.experimentInfo.zoom, true);
    }

    if (objJson.experimentScene) {
      components = objJson.experimentScene.componentList ? objJson.experimentScene.componentList : null;
    }

    if (objJson.experimentScene) {
      connections = objJson.experimentScene.connectionList ? objJson.experimentScene.connectionList : null;
    }

    //恢复所有器件
    if (components) {
      $.each(components, function (i, com) {
        var pro = com.uiProperty;
        var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(com);
        if (model) {
          _this.rootModel.addChildModel(model);
          model.setPosition(pro.x, pro.y, false);
        }
      });
    }

    //恢复连接
    var unrestoredConnections = new draw2d.util.ArrayList();
    if (connections) {
      $.each(connections, function (i, conn) {
        unrestoredConnections.add(conn);
      });
    }

    for (var i = 0; unrestoredConnections.getSize() > 0; ) {
      var connDes = unrestoredConnections.get(i);

      var sid = connDes.modelProperty.source_id;
      var tid = connDes.modelProperty.target_id;
      var spid = connDes.modelProperty.source_parent_id;
      var tpid = connDes.modelProperty.target_parent_id;

      var sPort = this.context.findPortModelById(spid, sid);
      var tPort = this.context.findPortModelById(tpid, tid);

      var restored = false;
      if (sPort && tPort) {
        this.makeConnection(sPort, tPort, connDes);
        restored = true;
      }

      if (restored) {
        unrestoredConnections.remove(connDes);
        i = 0;
        continue;
      }
      i++;
    }
    this.context.circuitparser.parse(true);
    this.commandStack.undostack = [];
    this.commandStack.redostack = [];
  },

  /**
   * 函数名称：Rainier.UI.V2.GraphicalEditor.makeConnection<br>
   * 函数功能：创建连接<br>
   * 参数输入：sourcePort:PortModel<br>
   * 参数输入：targetPort:PortModel<br>
   * 参数输入：conndes:Object（连接描述对象）<br>
   * 函数返回：无<br>
   * 异常信息：无<br>
   */
  makeConnection: function (sourcePort, targetPort, conndes) {
    var property = {};
    property.uiProperty = $.extend(true, {}, conndes.uiProperty);
    property.modelProperty = $.extend(true, {}, conndes.modelProperty);

    var conn = new Rainier.UI.V2.ConnectionModel(property);

    conn.setUuid(conndes.uuid);
    conn.attachSourcePort(sourcePort);
    sourcePort.attachOutgoing(conn);
    conn.attachTargetPort(targetPort);
    targetPort.attachIncoming(conn);
    this.rootModel.addConnection(conn);

    if (conndes.componentList) {
      $.each(conndes.componentList, function (i, joint) {
        var model = Rainier.UI.V2.DeviceModelBuilder.buildModel(joint);
        if (model) {
          conn.addChildModel(model, false);
        }
      });
    }
  },

  /**
   * @名称   clearEditor
   * @功能   清空实验平台的内容
   * @author 杨顺强
   * @data   2017-09-07
   * @return {[type]}   [description]
   */
  clearEditor: function () {
    var canvas = this.rootEditPart.figure;
    var figures = canvas.getFigures();
    var lines = canvas.getLines();
    canvas.getCommandStack().startTransaction(draw2d.Configuration.i18n.command.deleteShape);
    figures.each(function (index, figure) {
      var cmd = figure.createCommand(new draw2d.command.CommandType(draw2d.command.CommandType.DELETE));
      if (cmd !== null) {
        canvas.getCommandStack().execute(cmd);
      }
    });
    // execute all single commands at once.
    canvas.getCommandStack().commitTransaction();
  },
});
